unit LegacyStream;

interface

uses Classes, SysUtils;

type
  TSXLegacyStream = class(TStream)
  private
    FSource: TStream;
    FOffset, FSize,
    FPosition: int64;
  protected
    function GetSize: Int64; override;
    procedure SetSize(NewSize: Longint); overload; override;
    procedure SetSize(const NewSize: Int64); overload; override;
  public
    constructor Create(const Source: TStream; const WorkOffset,WorkSize: int64);

    function Read(var Buffer; Count: Longint): Longint; override;
    function Write(const Buffer; Count: Longint): Longint; override;
    function Seek(Offset: Longint; Origin: Word): Longint; overload; override;
    function Seek(const Offset: Int64; Origin: TSeekOrigin): Int64; overload; override;
  end;

implementation

uses RTLConsts;

{ TSXLegacyStream }

constructor TSXLegacyStream.Create(const Source: TStream; const WorkOffset,
  WorkSize: int64);
begin
  FSource := Source;
  FOffset := WorkOffset;
  FSize := WorkSize;
  FPosition := 0;
//  Assert(FOffset+FSize <= FSource.Size);
end;

function TSXLegacyStream.GetSize: Int64;
begin
  Result := FSize;
end;

function TSXLegacyStream.Read(var Buffer; Count: Integer): Longint;
begin
  FSource.Seek(FOffset+FPosition, soFromBeginning);
  Result := (FSize-FPosition);
  if Result > 0 then begin
    if Count > Result then Count := Result;
    Result := FSource.Read(Buffer, Count);
    Inc(FPosition, Result);
  end;
end;

function TSXLegacyStream.Seek(Offset: Integer; Origin: Word): Longint;
begin
{  case Origin of
    soFromBeginning: FPosition := Offset;
    soFromCurrent: Inc(FPosition, Offset);
    soFromEnd: FPosition := FSize-Offset;
  end;
  if (FPosition < 0
  Result := FPosition;}
  //raise EStreamError.CreateResFmt(@sSeekNotImplemented, [Classname]);
  Result := Seek(int64(Offset), TSeekOrigin(Origin));
end;

function TSXLegacyStream.Seek(const Offset: Int64;
  Origin: TSeekOrigin): Int64;
begin
  case Origin of
    soBeginning: FPosition := Offset;
    soCurrent: FPosition := FPosition+Offset;
    soEnd: FPosition := FSize-Offset;
  end;

  if (FPosition > FSize) or (FPosition < 0) then
    raise EStreamError.Create('Seek position out of range!');

  Result := FPosition;
end;

procedure TSXLegacyStream.SetSize(NewSize: Integer);
begin
  // We do nothing!
end;

procedure TSXLegacyStream.SetSize(const NewSize: Int64);
begin
  // We do nothing!
end;

function TSXLegacyStream.Write(const Buffer; Count: Integer): Longint;
begin
  raise EStreamError.Create('Legacy streams is read-only!');
end;

end.